<template>
    <div 
        class="claer" 
        ref="clear" 
        :style="{ width: clearWindow.width + 'px', height: clearWindow.height + 'px' }"
    ></div>

    <!-- 操作按钮 -->
    <el-button style="margin: 10px;" type="success" @click="startSimulation()">开始仿真</el-button>
</template>

<script setup lang="ts">
import * as THREE from "three";
import { onMounted, reactive, ref } from "vue";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import * as TWEEN from "three/examples/jsm/libs/tween.module.js";
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { CSG } from 'three-csg-ts';



let clear = ref();
// 定义 canvas 窗口宽高
let clearWindow = reactive({
    width:800,
    height:600
});
// let toolPosition = ref<THREE.Vector3>();
// 创建场景
const scene = new (THREE as any).Scene();
scene.background = new (THREE as any).Color(0xffffff);

//辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(10);
scene.add(axesHelper);


// 创建渲染器
const render = new THREE.WebGLRenderer({ antialias: true });
render.setSize(clearWindow.width, clearWindow.height);
render.setPixelRatio(window.devicePixelRatio);
render.setClearColor(0xffffff, 1);

// 创建相机
const camera = new (THREE as any).PerspectiveCamera(45, clearWindow.width / clearWindow.height, 0.1, 1000);
const bestLength = 30;
camera.position.x = bestLength;
camera.position.y = bestLength;
camera.position.z = bestLength;
camera.lookAt(0, 0, 0);

// 轨道滑动器
const controls = new OrbitControls(camera, render.domElement); //轨道滑动器
controls.enableDamping = true;  // 设置带阻尼的惯性
controls.dampingFactor = 0.1; // 设置阻尼系数
controls.rotateSpeed = 0.14; // 旋转速度

// 创建灯光
const createLight = (x: number, y: number, z: number) => {
    const color = 0xffffff; //  灯光颜色
    const intensity = 1; // 灯光强度
    const light = new (THREE as any).DirectionalLight(color, intensity);
    light.position.set(x, y, z);
    light.target.position.set(0, 0, 0);
    return light;
};
const lights = [
    createLight(bestLength, bestLength, -bestLength),
    createLight(-bestLength, bestLength, -bestLength),
    createLight(-bestLength, bestLength, bestLength),
    createLight(-bestLength, -bestLength, bestLength),
    createLight(bestLength, -bestLength, -bestLength),
    createLight(-bestLength, -bestLength, -bestLength),
    createLight(-bestLength, -bestLength, bestLength),
    createLight(bestLength, -bestLength, bestLength),
];
lights.forEach((light) => scene.add(light));
lights.forEach((light) => scene.add(light.target));

///////////////////////////////////////////////////////////////

let workpiece: THREE.Mesh, tool: THREE.Mesh, chipsGroup: THREE.Group;
// 定义毛坯参数
let workpieceInfo = {
    length: 15,
    width: 10,
    height: 6,
}
// 定义刀具参数为独立变量
const toolRadius = 0.5; // 刀具半径
const toolHeight = 6;   // 刀具长度
let toolInfo = {
    toolRadius,
    toolHeight,
    // 刀具初始位置
    position: {
        x : -toolRadius - workpieceInfo.length / 2,
        y : workpieceInfo.height / 2 + toolRadius / 2,
        z : -toolRadius - workpieceInfo.width / 2,
    }
};
// 创建毛坯
function createWorkpiece(length: number, width: number, height: number) {
    const geometry = new THREE.BoxGeometry(length, height, width,100,100,100);
    // const geometry = new THREE.BoxGeometry(length, height, width);
    const material = new THREE.MeshLambertMaterial({
        color: 0xd3d3d3,
        // metalness: 0.2,
        // roughness: 0.8,
        wireframe:true,
    });
    workpiece = new THREE.Mesh(geometry, material);
    // workpiece.position.set(length / 2, height / 2, width / 2);
    workpiece.position.set(0, 0, 0);
    workpiece.receiveShadow = true;
    workpiece.castShadow = true;
    scene.add(workpiece);
    return workpiece;
}

// 创建铣削刀具
function createTool(radius: number, widthSegments: number, heightSegments: number, position: THREE.Vector3) {
    // 创建刀柄
    const handleGeometry = new THREE.CylinderGeometry(radius, radius, toolHeight, 32);
    const handleMaterial = new THREE.MeshStandardMaterial({
        color: 0xffffff,
        // metalness: 0.9,
        // roughness: 0.2,
        wireframe:true,
    });

    // 创建刀头
    const tipGeometry = new THREE.SphereGeometry(radius, widthSegments , heightSegments , 32);
    const tipMaterial = new THREE.MeshStandardMaterial({
        color: 0x808080,
        metalness: 0.9,
        roughness: 0.2
    });

    // 创建刀具
    // const toolGeometry = new THREE.SphereGeometry(radius, widthSegments , heightSegments , 32);
    // const toolMaterial = new THREE.MeshStandardMaterial({
    //     color: 0x808080,
    //     metalness: 0.9,
    //     roughness: 0.2
    // });


    //组合刀具
    const toolHandle = new THREE.Mesh(handleGeometry, handleMaterial);
    const toolTip = new THREE.Mesh(tipGeometry, tipMaterial);
    toolHandle.position.copy(new THREE.Vector3(toolInfo.position.x, toolInfo.position.y + 3, toolInfo.position.z));
    toolTip.position.copy(position);

    toolTip.updateMatrixWorld();
    toolHandle.updateMatrixWorld();
    // tool = toolHandle;
    tool = CSG.union(toolTip, toolHandle);
    tool.castShadow = true;

    // 设置刀具位置
    tool.position.copy(position);
    scene.add(tool);
    return tool;
}

// 创建切屑组
// function createChipsGroup() {
//     chipsGroup = new THREE.Group();
//     scene.add(chipsGroup);
// }

// let toolPathPoints: THREE.Vector3[] = []; // 刀具路径
interface pointPosition {
    x?: number;
    y?: number;
    z?: number;
}
let toolPathPoints: pointPosition[] = []; // 刀具路径
const depth = 3; // 基于滑块的切削深度
// 生成刀具路径
function generateToolPath() {
    // // 定义路径点
    toolPathPoints.push({ x: toolInfo.position.x, y: toolInfo.position.y - depth, z: toolInfo.position.z });    // 刀具下降
    toolPathPoints.push({ x: toolInfo.position.x + 2 * toolInfo.toolRadius, y: toolInfo.position.y - depth, z: toolInfo.position.z + 2 * toolInfo.toolRadius });    // 刀具右移
    toolPathPoints.push({ x: toolInfo.position.x + 2 * toolInfo.toolRadius, y: toolInfo.position.y - depth, z: toolInfo.toolRadius + workpieceInfo.width / 2 }); 
    toolPathPoints.push({ y: toolInfo.position.y });    // 刀具上升
    toolPathPoints.push({ x: toolInfo.position.x, y: toolInfo.position.y, z: toolInfo.position.z });    // 返回到初始位置
}
let nowCube: THREE.Mesh;
// 添加模型和刀具到场景中
const addModelAndTool = async () => {
    createWorkpiece(workpieceInfo.length, workpieceInfo.width, workpieceInfo.height);// 创建毛坯
    tool = createTool(toolRadius, 64,32, new THREE.Vector3(toolInfo.position.x, toolInfo.position.y, toolInfo.position.z));// 创建铣削刀具
    nowCube = workpiece;
};

let index = 0
let isAnimating = false
let animationTime: number[] = [1000, 1000, 5000, 1000, 1000]

const animateLoop = async () => {
    if (index >= toolPathPoints.length) {
        isAnimating = false;
        return;
    }
    scene.remove(nowCube);
    const pos = toolPathPoints[index];
    new TWEEN.Tween(tool.position)
        .to({ x: pos.x, y: pos.y, z: pos.z }, animationTime[index])
        .onUpdate(() => {
            scene.remove(nowCube);
            // tool.updateMatrixWorld();
            // nowCube = CSG.subtract(nowCube, tool);
            if (processWorkpieceCut(nowCube, tool)) {
                scene.add(nowCube); // 刷新显示
            }
            scene.add(nowCube);
        })
        .onComplete(() => {
            index++;
            isAnimating = false;
            animateLoop();
        })
        .start();
};

// function processWorkpieceCut(workpiece: THREE.Mesh, tool: THREE.Mesh): boolean {
//     const workpieceBox = new THREE.Box3().setFromObject(workpiece);
//     const toolBox = new THREE.Box3().setFromObject(tool);
//     if (!workpieceBox.intersectsBox(toolBox)) return false;

//     const toolLocalPos = workpiece.worldToLocal(tool.position.clone());
//     const geometry = workpiece.geometry as THREE.BufferGeometry;
//     const positionAttr = geometry.getAttribute('position');
//     const minValidHeight = 0;
//     let isCut = false;

//     for (let i = 0; i < positionAttr.count; i++) {
//         const vertex = new THREE.Vector3().fromBufferAttribute(positionAttr, i);
//         const dx = vertex.x - toolLocalPos.x;
//         const dy = vertex.y - toolLocalPos.y;
//         const dz = vertex.z - toolLocalPos.z;
//         const distanceSq = dx * dx + dy * dy + dz * dz;

//         if (distanceSq <= toolRadius * toolRadius) {
//             const remaining = toolRadius * toolRadius - dx * dx - dz * dz;
//             if (remaining >= 0) {
//                 const deltaY = Math.sqrt(remaining);
//                 let new_y = toolLocalPos.y - deltaY;
//                 new_y = Math.max(new_y, minValidHeight);

//                 if (vertex.y > new_y) {
//                     positionAttr.setXYZ(i, vertex.x, new_y, vertex.z);
//                     isCut = true;
//                 }
//             }
//         }
//     }

//     if (isCut) {
//         positionAttr.needsUpdate = true;
//         geometry.computeVertexNormals();
//     }

//     return isCut;
// }

function processWorkpieceCut(workpiece: THREE.Mesh, tool: THREE.Mesh): boolean {
    const workpieceBox = new THREE.Box3().setFromObject(workpiece);
    const toolBox = new THREE.Box3().setFromObject(tool);
    if (!workpieceBox.intersectsBox(toolBox)) return false;

    const toolLocalPos = workpiece.worldToLocal(tool.position.clone());
    const geometry = workpiece.geometry as THREE.BufferGeometry;
    const positionAttr = geometry.getAttribute('position');
    let isCut = false;

    // 球头半球形切割逻辑
    for (let i = 0; i < positionAttr.count; i++) {
        const vertex = new THREE.Vector3().fromBufferAttribute(positionAttr, i);
        const dx = vertex.x - toolLocalPos.x;
        const dz = vertex.z - toolLocalPos.z;
        const distanceXZSq = dx * dx + dz * dz;

        // 条件1：顶点在 x-z 平面内位于刀具半径范围内
        if (distanceXZSq <= toolRadius * toolRadius) {
            // 计算球头下表面半球形曲面对应的 y 值
            const remaining = toolRadius * toolRadius - distanceXZSq;
            if (remaining >= 0) {
                const deltaY = Math.sqrt(remaining);
                const sphereSurfaceY = toolLocalPos.y - deltaY; // 半球曲面高度

                // 条件2：顶点 y 坐标高于球头下表面半球形曲面
                if (vertex.y > sphereSurfaceY) {
                    // 将顶点 y 坐标裁剪到球头下表面半球形曲面
                    positionAttr.setXYZ(i, vertex.x, sphereSurfaceY, vertex.z);
                    isCut = true;
                }
            }
        }
    }

    if (isCut) {
        positionAttr.needsUpdate = true;
        geometry.computeVertexNormals();
    }

    return isCut;
}



function createGui(mesh:THREE.Mesh) { 
    const gui = new GUI();//创建GUI对象 
    gui.domElement.style.right = '0px';
    gui.domElement.style.width = '300px';
    gui.add(mesh.position, 'x', -10, 10);
    gui.add(mesh.position, 'y', -10, 10);
    gui.add(mesh.position, 'z', -10, 10);
}
// 点击按钮开始仿真 布尔运算
function startSimulation() {
    animateLoop();
}

//  渲染函数
const animate = () => {
    controls.update(); // 轨道滑动器更新
    requestAnimationFrame(animate); // 递归调用
    render.render(scene, camera); // 渲染
    (TWEEN as any).update(); // 更新动画
};


// 挂载
onMounted(() => {
    clear.value.appendChild(render.domElement);
    animate();
    //////////////////////////
    addModelAndTool();// 添加模型和刀具
    generateToolPath();// 生成刀具路径
    createGui(tool);// 创建GUI
    //////////////////////////
});
</script>

<style lang="less">
.claer {
    border: 1px solid #ccc;
    margin: 10px;
}
</style>